package edu.towson.cosc.cosc455.brandonmoodyProject1;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.StringTokenizer;

import edu.towson.cosc.cosc455.interfaces.LexicalAnalyzer;

public class MyLexicalAnalyzer implements LexicalAnalyzer {
	private String fileStringCopy;
    private char nextChar;
    private int currentPosition;
    protected Token currentToken;
    protected StringBuilder lexemeBuffer;
    static String delim = " \n\r\t,.;"; //all token delimeters
	static ArrayList<String> charTokenArray = new ArrayList<String>();
	static ArrayList<String> stringTokenArray = new ArrayList<String>();
	static String fileName;
	static String file;
	public static String stringToken;
	static String charToken;
	public static MyLexicalAnalyzer Lexer;
	public static boolean foundError=false;
	static String varDefineNode;
	static String varUseNode;

    public void start(String fileString) throws CompilerException {
        fileStringCopy = fileString;
        currentPosition = 0;
        getCharacter();
        getNextToken();
    }
    int i=0;
    public void getNextToken() 
    {
        newBuffer();
        skipSpaces();
        addCharacter();
        getCharacter();
        // Sucks in character values
        while ((nextChar != '\n') && (nextChar != ' ')) {
            addCharacter();
            getCharacter();
        }
        // Combines characters to form a string
        String lexeme = lexemeBuffer.toString();
        // Forms the currentToken
        this.currentToken = Token.fromLexeme(lexeme);
    }
    
        //Resets the lexeme buffer to empty
        private void newBuffer() {
            lexemeBuffer = new StringBuilder();
        }

        @Override
        public void getCharacter() {
        	if (currentPosition < fileStringCopy.length()) {
                nextChar = fileStringCopy.charAt(currentPosition);
                currentPosition++;
            } else {
                nextChar = '\n';
            }
        }

        @Override
        public void addCharacter() 
        {
        lexemeBuffer.append(nextChar);
        }

        @Override
        public boolean isSpace(char c) {
              if (c==' ') 
                {
                    return true;
                }
                else 
                {
                    return false;
                }
            }
        
		   public void skipSpaces() {
	         while (isSpace(nextChar)) 
		      {
	        	 getCharacter();
		      }
		   }

        @Override
        public boolean lookupToken() {
                // TODO Auto-generated method stub
                return false;
        }
        
        public static String validateFileReadIn(String args) throws IOException 
    	{
        	final String markdownLanguage = "mkd";//declaration for markdown language extension
        	String fileLocation="C:\\Users\\Brandon\\Downloads\\Test Cases\\Test Cases\\";
    		String fileName=fileLocation+args;
    		String extension = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
    		if(!markdownLanguage.equalsIgnoreCase(extension))
    		{
    			System.out.println("ERROR:Please input a valid .mkd file type");
    		}
    		else
    		MyCompiler.fileNameNoExtension=args.substring(0,args.lastIndexOf("."));
    		return fileName;
    	}
        
        public static void splitToSmallerStrings (String c) throws IOException
        {
        String[] result = c.split("");
        for (int x=0; x<result.length; x++)
        	charTokenArray.add(result[x]);
        }
        
        public static String fileBuffer(String fileName) throws IOException 
    	{
    	    BufferedReader br = new BufferedReader(new FileReader(fileName));
    	    try {
    	        StringBuilder sb = new StringBuilder();
    	        String line = br.readLine();
    	        while (line != null) {
    	            sb.append(line);
    	            sb.append("\n");
    	            line = br.readLine();
    	        }
    	        return sb.toString();
    	    } finally {
    	        br.close();
    	    }
    	}
        
        public static void visualTranslation(String fileString, String fileName) throws IOException
    	{
        	StringBuilder sb=new StringBuilder();
            StringTokenizer st = new StringTokenizer(fileString,delim);
            int i=0;
            BufferedWriter out=new BufferedWriter(new FileWriter(fileName +".html"));
            while (st.hasMoreTokens()) {
            	stringTokenArray.add(st.nextToken());
                i++;
            }
            System.out.println();
    		i=0;
    		int startDocumentNo = 0;
    		int startHeadNo=0;
    		boolean boldOpen=false;
    		boolean documentOpen=false;
    		boolean headOpen=false;
    		boolean titleOpen=false;
    		boolean paragraphOpen=false;
    		boolean italicsOpen=false;
    		boolean listOpen=false;
    		boolean itemOpen=false;
    		boolean audioOpen=false;
    		boolean videoOpen=false;
    		boolean defineOpen=false;
    		boolean useOpen=false;
    		stringToken=stringTokenArray.get(i);
    		while(i<stringTokenArray.size())
    		{
    			if(i==stringTokenArray.size()-1)
    			{
    				System.out.println("Reached end of file");
    				i=stringTokenArray.size();
    			}
    			else
    			{
    				 if (stringToken.equalsIgnoreCase("#start"))
    				{
    					 stringToken=stringTokenArray.get(i+1);
    					 if(stringToken.equalsIgnoreCase("document")){
    						 documentOpen=true;
    						 startDocumentNo=startDocumentNo+1;
    						 sb.append("<html>");
    						 stringToken=stringTokenArray.get(i+2);
    						 i=i+2;
    					 }
    					 else if(stringToken.equalsIgnoreCase("head")){
    						 	headOpen=true;
    						 	startHeadNo=startHeadNo+1;
    							sb.append("<html>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    				}
    					 else  if(stringToken.equalsIgnoreCase("title")){ 
    						 	titleOpen=true;
    							sb.append("<title>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("paragraph")){
    						 	paragraphOpen=true;
    							sb.append("<p>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("bold")){
    							sb.append("<b>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    							boldOpen=true;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("italics")){
    						 	italicsOpen=true;
    							sb.append("<i>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("list")){
    						 	listOpen=true;
    							sb.append("<ul>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else if(stringToken.equalsIgnoreCase("item")){ 
    						 	itemOpen=true;
    							sb.append("<li>");
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("audio")){
    						 	audioOpen=true;
    							sb.append("<audio controls>");
    							sb.append("source src="+stringToken);
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("video")){
    						 	videoOpen=true;
    							stringToken=stringTokenArray.get(i+2);
    							sb.append("<iframe src="+stringToken+"/>");
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("define")){
    							defineOpen=true;
    							stringToken=stringTokenArray.get(i+2);
    							i=i+2;
    					 }
    					 else  if(stringToken.equalsIgnoreCase("use")){
    						 	useOpen=true;
    							sb.append(varUseNode+" ");
    							stringToken=stringTokenArray.get(i+5);
    							i=i+5;
    					 }
    					 else
    					 {
    						 foundError=true;
    					 	 System.out.println("\n"+"STOPPING COMPILATION (Syntax Error: #Start must be followed by a legal lexeme)"+"\n");
    					 	 i=stringTokenArray.size();
    					 	 sb.append("\n"+"STOPPING COMPILATION (Syntax Error: #Start must be followed by a legal lexeme)"+"\n");
    					 }
    				}
    				else if(stringToken.equalsIgnoreCase("#end"))
    				{
    					stringToken=stringTokenArray.get(i+1);
    					 if(stringToken.equalsIgnoreCase("document")&&(documentOpen==true)){
    							i=stringTokenArray.size();
    							sb.append("</html>");
    							 }
    							 else if(stringToken.equalsIgnoreCase("head")&&(headOpen==true)){
    	    							sb.append("</head> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    						}
    							 else  if(stringToken.equalsIgnoreCase("title")&&(titleOpen==true)){
    	    							sb.append("</title> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("paragraph")&&(paragraphOpen==true)){
    	    							sb.append("</p> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("bold")&&(boldOpen==true)){
    	    							sb.append("</b> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("italics")&&(italicsOpen==true)){
    	    							sb.append("</i> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("list")&&(listOpen==true)){
    	    							sb.append("</ul> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else if(stringToken.equalsIgnoreCase("item")&&(itemOpen==true)){
    	    							sb.append("</li> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("audio")&&(audioOpen==true)){
    	    							sb.append("</audio> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("video")&&(videoOpen==true)){
    	    							sb.append("</video> ");
    									stringToken=stringTokenArray.get(i+2);
    									i=i+2;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("define")&&(defineOpen==true)){
    									stringToken=stringTokenArray.get(i+1);
    									sb.append(stringToken);
    									i=i+1;
    							 }
    							 else  if(stringToken.equalsIgnoreCase("use")&&(useOpen==true)){
    									stringToken=stringTokenArray.get(i+1);
    									sb.append(stringToken);
    									i=i+1;
    							 }
    							 else
    							 {
    								 System.out.println("COMPILATION STOPPED: Error Found");
    								 foundError=true;
    							 	 i=stringTokenArray.size();
    							 }
    						}
    				else if(stringToken.equalsIgnoreCase("#newline"))
    				{
    					sb.append("<br>");
    					stringToken=stringTokenArray.get(i+1);
    				}
    				else if(stringToken.equalsIgnoreCase("#name"))
    				{
    					stringToken=stringTokenArray.get(i+1);
    					varDefineNode=stringToken;
    					i++;
    				}
    				else if(stringToken.equalsIgnoreCase("#value"))
    				{
    					stringToken=stringTokenArray.get(i+1);
    					varUseNode=stringToken;
    					i++;
    				}
    				else if(stringToken.charAt(0)==('#')&&(!stringToken.equals(Token.TERMINAL_START)))
    				{
    					foundError=true;
    					System.out.println("COMPILATION STOPPED: Error Found");
    					i=stringTokenArray.size();
    				}
    				else
    				{
    					sb.append(stringToken+" ");
    					stringToken=stringTokenArray.get(i+1);
    					i++;
    				}
    			}
    		}
    		if (!foundError&&!(startHeadNo>1)&&!(startDocumentNo>1)){
    			out.write(sb.toString());
    			out.close();
    		}
    		else
    		{
    			System.out.println("COMPILATION STOPPED: Error Found");
    			out.close();
    		}
    	}
}